PHP applet payment function full version [based on thinkPHP]

  • 2021-12-04 18:15:00
  • OfStack

In this paper, the payment function of PHP applet is described as an example. Share it for your reference, as follows:

Environment: tp3.2 + Applet WeChat payment function is opened

Step1: Download PHP and pay SDK (download address) and put it under Library\ Vendor, and name it Wxpay

Modify appid appsecret key MCHID in WxPay. Config. php

Step2: Applet js code:


var url = getApp().globalData.httpServer + 'api/buy/pay';
var userId = getApp().globalData.userId;
var totalMoney = this.data.totalMoney;
var cart = this.data.goods;
var param = {
  cart: JSON.stringify(cart),
  cartamount: totalMoney,
  userid: userId,
  payment: this.data.payment,
  addressid: defaultAddress.id
};
var that = this;
util.http(url, param, function (ret) {
  if (ret.data.code == 1) {
    if (that.data.payment == 'balance') { //  Balance payment 
      that.afterPaySuccess(ret.data.data);
    } else {                //  WeChat payment 
      wx.requestPayment({
        timeStamp: ret.data.data.timeStamp,
        nonceStr: ret.data.data.nonceStr,
        package: ret.data.data.package,
        signType: ret.data.data.signType,
        paySign: ret.data.data.paySign,
        'success': function (res) {
          that.afterPaySuccess(ret.data.data.orderid);
        },
        'fail': function (res) {
          console.log(res);
        }
      })
    }
  } else {
    util.showTip(ret.data.msg, ' Submission of order failed ');
  }
});
/**
 *  Network request 
 */
function http(url, params, callback) {
  wx.request({
    url: url,
    data: params,
    success: function (res) {
      callback(res);
    },
    fail: function (err) {
      console.log(err);
    }
  });
}

Step3: Interface code:


public function pay()
{
    $cart = I('cart', '', 'trim');
    $cartAmount = I('cartamount');
    $addressId = I('addressid', 0, 'intval');
    $payment = I('payment', '', 'trim');
    $userId = $this->userid;
    $cart = json_decode($cart, true);
    if (empty($cart)) {
      $result['msg'] = ' Shopping cart acquisition failed ';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
    $totalMoney = 0;
    foreach ($cart as $goods) {
      $money = $goods['price'];  // price
      $selectCount = $goods['selectcount'];  // price
      $itemAmount = number_format($money * $selectCount, 2, '.', '');
      $totalMoney += $itemAmount;
    }
    //  Check whether the total amount is 1 To 
    if ($totalMoney != $cartAmount) {
      $result['msg'] = ' Total amount does not match :' . $totalMoney;
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
    //  Get the user address 
    $address = M('MemberAddress')->where('userid=' . $userId . " and id=" . $addressId)->find();
    if (empty($address)) {
      $result['msg'] = ' User address does not exist ';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
    //  User information 
    $user = M('Member')->where("id=" . $userId)->find();
    if ($payment == 'balance') {
      if ($user['amount'] < $cartAmount) {
        $result['msg'] = ' Insufficient balance ';
        $result['code'] = 0;
        $this->ajaxReturn($result);
      }
    }
    //  Generate an order 
    $order['ordersn'] = $this->genOrdersn($user['id']);
    $order['price'] = $cartAmount;
    $order['addressid'] = $address['id'];
    $order['addressinfo'] = serialize($address); //json_encode($address);
    $order['longitude'] = $address['longitude'];
    $order['latitude'] = $address['latitude'];
    $order['addtime'] = time();
    $order['status'] = 0;
    $order['userid'] = $user['id'];
    $order['paytype'] = $payment;
    $order['paysn'] = '';
    $order['paytime'] = time();
    $orderId = M("Order")->add($order);
    if ($orderId == 0) {
      $result['msg'] = ' Failed to create order ';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
    foreach ($cart as $goods) {
      $orderGoods['orderid'] = $orderId;
      $orderGoods['goodsid'] = $goods['id'];
      $orderGoods['title'] = $goods['title'];
      $orderGoods['price'] = $goods['price'];
      $orderGoods['attr'] = $goods['attr'];
      $orderGoods['pic'] = $goods['pic'];
      $orderGoods['num'] = $goods['selectcount'];
      M("OrderGoods")->add($orderGoods);
    }
    if ($payment == 'balance') {
      //  Balance payment 
      $this->balancePay($cartAmount, $user['wxopenid'], $orderId);
    } else if ($payment == 'weixin') {
      //  WeChat payment 
      $this->weixinPay($cartAmount, $user['wxopenid'], $orderId, $order['ordersn']);
    }
}
/**
*  WeChat payment 
* @author  Big face cat big face 
* @param $cart
* @param $cartAmount
* @param $address
* @param $user
*/
private function weixinPay($cartAmount, $openId, $orderId, $orderSn)
{
    import("Vendor.Wxpay.lib.WxPay#Api", "", ".php");
    // Order number 
    $money = $cartAmount * 100;
    $openid = $openId;
    $input = new \WxPayUnifiedOrder();
    $input->SetBody(" Dick - Commodity ");
    $input->SetOut_trade_no("$orderSn");
    $input->SetTotal_fee("$money");
    $input->SetNotify_url("https://" . $_SERVER['HTTP_HOST'] . "/api/buy/payNotify");
    $input->SetTrade_type("JSAPI");
    $input->SetOpenid($openid);
    $unifiedOrder = \WxPayApi::unifiedOrder($input);
    if ($unifiedOrder['result_code'] == 'SUCCESS' && $unifiedOrder['return_code'] == 'SUCCESS') {
      $time = time();
      $data['timeStamp'] = "$time";              // Time stamp 
      $data['nonceStr'] = $unifiedOrder['nonce_str'];     // Random string 
      $data['signType'] = 'MD5';                // Signature algorithm, temporarily supported  MD5
      $data['package'] = 'prepay_id=' . $unifiedOrder['prepay_id'];  // Unified 1 Object returned by the single interface  prepay_id  Parameter value, submission format such as: prepay_id=*
      $data['paySign'] = $this->genPaySign($unifiedOrder, $time);//  I thought it was $unifiedOrder['sign'];  It was later discovered that this method was called .  For the signature scheme, please refer to WeChat WeChat official account Payment Help Document ;
      $data['out_trade_no'] = $orderSn;
      $data['orderid'] = $orderId;
      $return['code'] = 1;
      $return['data'] = $data;
    } else {
        Log::write(var_export($unifiedOrder, true), Log::ERR, '', C('LOG_PATH')."wx_pay_".date('y_m_d').'.log');
        $return['code'] = 0;
        $return['msg'] = ' WeChat payment failed ';// $unifiedOrder['RETURN_MSG'];
    }
    $this->ajaxReturn($return);
}
/*  Generate payment signature */
private function genPaySign($unifiedOrder, $time)
{
    $appId = \WxPayConfig::APPID;
    $nonceStr = $unifiedOrder['nonce_str'];
    $package = 'prepay_id=' . $unifiedOrder['prepay_id'];
    $signType = "MD5";
    $timeStamp = $time;
    $key = \WxPayConfig::KEY;
    $sign = md5(sprintf("appId=%s&nonceStr=%s&package=%s&signType=%s&timeStamp=%s&key=%s", $appId, $nonceStr, $package, $signType, $timeStamp, $key));
    return $sign;
}
/**
*  Payment callback 
* @author: Big face cat big face 
*/
public function payNotify()
{
    import("Vendor.Wxpay.lib.WxPay#Data", "", ".php");
    $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
    $val = \WxPayResults::Init($xml);
    if ($val['result_code'] == 'SUCCESS' && $val['return_code'] == 'SUCCESS') {
      $orderSn = $val['out_trade_no'];
      $transactionId = $val['transaction_id'];
      $data = array('paytype' => 'weixin', 'status' => '1', 'paytime' => time(), 'paysn' => $transactionId);
      M("Order")->where("ordersn='$orderSn'")->setField($data);
      exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
    }else {
      Log::write(var_export($val, true), Log::ERR, '', C('LOG_PATH')."wx_pay_notify_".date('y_m_d').'.log');
      exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
    }
}

In payNotify callback method, 1 must pay attention to returning

< xml > < return_code > < ![CDATA[SUCCESS]] > < /return_code > < return_msg > < ![CDATA[OK]] > < /return_msg > < /xml >

If you don't process it, you will find that payNotify will be executed many times. See also: Official Documentation

Summary 1: Pay attention to 2 points, 1. The problem of signature 2. The return processing of callback method.

You are welcome to correct me.

For more readers interested in PHP related content, please check the topics of this site: "Summary of PHP WeChat Development Skills", "Summary of php curl Usage", "Summary of php String Usage (string)", "Summary of json Format Data Operation Skills in PHP" and "Summary of PHP File Operation Skills for XML"

I hope this article is helpful to everyone's PHP programming.


Related articles: